# uncompyle6 version 3.2.3
# Python bytecode 3.6 (3379)
# Decompiled from: Python 3.6.8 |Anaconda custom (64-bit)| (default, Feb 21 2019, 18:30:04) [MSC v.1916 64 bit (AMD64)]
# Embedded file name: bxss\bxss.py
__author__ = "blade"
__maintainer__ = "Attila Gerendi (Sanyi)"
import logging, os, requests, json, tempfile, platform
from subprocess import PIPE, Popen
from subprocess import SubprocessError
from requests.packages.urllib3.exceptions import InsecureRequestWarning

requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
logger = logging.getLogger("bxss")


class BXSSHelperError(Exception):
    """Exception indicating that there was a problem with BXSS"""

    pass


class BXSSAcuMonitorConnectionError(BXSSHelperError):
    """unable to start connect to AcuMonitor server"""

    pass


class BXSSJsonParseError(BXSSHelperError):
    """unable to parse json response from acumonitor"""

    pass


class BXSSJsonProcessError(BXSSHelperError):
    """error while executing """

    pass


class BXSSWVSNotFoundError(BXSSHelperError):
    """wvs was not found in the configured path"""

    pass


class BXSSHelper:
    """Performs AcuMonitor related tasks: register a new AcuMonitor user and poll AcuMonitor server for new alerts"""

    BXSS_BASE_URL = "https://bxss.me/"

    def __init__(self, wvs_dir, wvs_exe="acumonitor", requests_proxies_cb=None):
        """Instantiate the class, wvs_saved_tests_dir (the directory where saved tests are stored) is required"""
        self.wvs_directory = wvs_dir
        if platform.system() == "Windows":
            if not wvs_exe.endswith(".exe"):
                wvs_exe += ".exe"
        self.wvs_executable = wvs_exe
        self.proxies_cb = requests_proxies_cb

    def process_vulns(self, vulns):
        tmp_file_path = None
        try:
            tmp_file_path = tempfile.mktemp()
            with open(tmp_file_path, "w+") as (tmpFileHandler):
                json.dump(vulns, tmpFileHandler)
            args = [
                os.path.join(self.wvs_directory, self.wvs_executable),
                "/genalert",
                tmp_file_path,
            ]
            if not os.path.isfile(args[0]):
                raise BXSSWVSNotFoundError()
            import subprocess

            process = Popen(
                args,
                cwd=self.wvs_directory,
                creationflags=getattr(subprocess, "CREATE_NEW_PROCESS_GROUP", 0),
                stderr=PIPE,
                stdout=PIPE,
            )
            std_outs, std_errors = process.communicate(timeout=30)
            if std_outs is not None:
                pass
            try:
                data = std_outs.decode("utf-8")
                logger.debug("genalert response: %s", data)
                if data:
                    output = json.loads(data)
                    return output
            except json.JSONDecodeError:
                raise BXSSJsonParseError()

        except SubprocessError:
            raise BXSSJsonProcessError()
        finally:
            if tmp_file_path:
                os.remove(tmp_file_path)

    def register_to_acumonitor(
        self, email, licence_key, wvs_version, wvs_build, company, host, ip
    ):
        """
        Register WVS installation to AcuMonitor.
        If successful, returns a tuple containing (api_key, acumonitor_user_id),
        e.g. ('f61f2d2d-c11e-461d-8469-0c4924bdc4a2', '009247')
        Returns False in case of failure
        """
        try:
            r = requests.post(
                self.BXSS_BASE_URL + "ng/register",
                verify=False,
                data=dict(
                    email=email,
                    lic=licence_key,
                    ver=wvs_version,
                    build=wvs_build,
                    company=company,
                    host=host,
                    ip=ip,
                ),
                proxies=self.proxies_cb() if self.proxies_cb else None,
            )
            if r.text:
                resp = json.loads(r.text)
                if resp["success"] is True:
                    return (resp["api_key"], resp["user_id"])
            return False
        except json.JSONDecodeError:
            raise BXSSJsonParseError()
        except requests.ConnectionError:
            raise BXSSAcuMonitorConnectionError()

    def poll_acumonitor(self, bxss_api_key, bxss_user_id):
        """
        Poll AcuMonitor for new alerts.
        If successful, returns a list of vulns
        """
        try:
            r = requests.post(
                self.BXSS_BASE_URL + "ng/poll",
                verify=False,
                data=dict(user_id=bxss_user_id, token=bxss_api_key),
                proxies=self.proxies_cb() if self.proxies_cb else None,
            )
            logger.debug("poll %s", r)
            if r.text:
                resp = json.loads(r.text)
                logger.debug("poll result %s", resp)
                if resp["success"] is True:
                    if "vulns" in resp:
                        return resp["vulns"]
            return []
        except json.JSONDecodeError:
            raise BXSSJsonParseError()
        except requests.ConnectionError:
            raise BXSSAcuMonitorConnectionError()
